#include "cond.h"
#include "lock.h"

/* clear queue */
void do_condition_init(condition_t *condition)
{
    queue_init(&(condition->waiting_queue));
}

/* The lock has been obtained before the task calls the function */
void do_condition_wait(mutex_lock_t *lock, condition_t *condition)
{
    /* [1] release the lock so other task can operate on the condition */
    queue_push(&(condition->waiting_queue), current_running[core_id]);
    current_running[core_id]->status = TASK_BLOCKED;
    do_mutex_lock_release(lock);

    /* [2] do scheduler */
    do_scheduler();

    /* [3] acquire lock */
    do_mutex_lock_acquire(lock);
}

/* unblock one task */
void do_condition_signal(condition_t *condition)
{
    if (!queue_is_empty(&(condition->waiting_queue)))
    {
        pcb_t *first_task;
        first_task = queue_dequeue(&(condition->waiting_queue));
        first_task->status = TASK_READY;
        queue_push(&ready_queue, first_task);
    }
}

/* unblock all task */
void do_condition_broadcast(condition_t *condition)
{
    while (!queue_is_empty(&(condition->waiting_queue)))
    {
        pcb_t *first_task;
        first_task = queue_dequeue(&(condition->waiting_queue));
        first_task->status = TASK_READY;
        queue_push(&ready_queue, first_task);
    }
}